﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Gavel.Common.Component.Extension;
using Gavel.Common.Component.Model;

namespace Gavel.Common.Component.Controls;

/// <summary>
/// 分页控件
/// </summary>
public class Pagination : Control
{
    /// <summary>
    /// 静态构造绑定默认样式
    /// </summary>
    static Pagination() => DefaultStyleKeyProperty.OverrideDefaultStyle<Pagination>();

    public static readonly DependencyProperty PositionProperty = nameof(PositionProperty).Register<Pagination, int>(new PropertyMetadata(1, OnPaginationChanged));

    public int Position
    {
        get => (int)GetValue(PositionProperty);
        set => SetValue(PositionProperty, value);
    }

    public static readonly DependencyProperty SizeProperty = nameof(SizeProperty).Register<Pagination, int>(new PropertyMetadata(10, OnPaginationChanged));

    public int Size
    {
        get => (int)GetValue(SizeProperty);
        set => SetValue(SizeProperty, value);
    }

    public static readonly DependencyProperty TotalProperty = nameof(TotalProperty).Register<Pagination, int>(new PropertyMetadata(0, OnPaginationChanged));

    public int Total
    {
        get => (int)GetValue(TotalProperty);
        set => SetValue(TotalProperty, value);
    }

    public static readonly DependencyProperty PagersProperty = nameof(PagersProperty).Register<Pagination, IEnumerable<PaginationItem>>();

    public IEnumerable<PaginationItem> Pagers
    {
        get => (IEnumerable<PaginationItem>)GetValue(PagersProperty);
        set => SetValue(PagersProperty, value);
    }

    public static readonly DependencyProperty SizeItemsProperty = nameof(SizeItemsProperty).Register<Pagination, IEnumerable<int>>([10, 20, 30, 50, 100]);

    public IEnumerable<int> SizeItems
    {
        get => (IEnumerable<int>)GetValue(SizeItemsProperty);
        set => SetValue(SizeItemsProperty, value);
    }

    public static readonly DependencyProperty SummaryProperty = nameof(SummaryProperty).Register<Pagination, string>();

    public string Summary
    {
        get => (string)GetValue(SummaryProperty);
        set => SetValue(SummaryProperty, value);
    }

    public static readonly DependencyProperty PageCommandProperty = nameof(PageCommandProperty).Register<Pagination, ICommand>();

    public ICommand PageCommand
    {
        get => (ICommand)GetValue(PageCommandProperty);
        set => SetValue(PageCommandProperty, value);
    }

    private static void OnPaginationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((Pagination)d).UpdatePages();
        ((Pagination)d).UpdateSummary();
    }

    private int TotalPages => (int)Math.Ceiling((double)Total / Size);

    private void UpdatePages()
    {
        var pages = new List<PaginationItem>();
        const int neighborPages = 3;
        int start = Math.Max(1, Position - neighborPages);
        int end = Math.Min(TotalPages, Position + neighborPages);

        // 添加前导省略号
        if (start > 1)
        {
            pages.Add(new PaginationItem { IsEllipsis = true });
        }

        for (int i = start; i <= end; i++)
        {
            pages.Add(new PaginationItem
            {
                Position = i,
                IsCurrent = i == Position,
                Visible = Visibility.Visible
            });
        }

        // 添加尾部省略号
        if (end < TotalPages)
        {
            pages.Add(new PaginationItem { IsEllipsis = true });
        }

        Pagers = pages;
    }

    private void UpdateSummary()
    {
        Summary = $"共{Total}条 | 第 {Position}/{TotalPages} 页";
    }
    
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        if (GetTemplateChild("PART_PreviousPage") is Button prevBtn)
        {
            prevBtn.Click += (_, _) => Position = TotalPages == 0 ? 0 : Math.Max(1, Position - 1);
        }

        if (GetTemplateChild("PART_NextPage") is Button nextBtn)
        {
            nextBtn.Click += (_, _) => Position = TotalPages == 0 ? 0 : Math.Min(TotalPages, Position + 1);
        }

        PageCommand = new RelayCommand<int>(p => Position = p);
        UpdateSummary();
    }
}